// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html



import { selfCls } from "../common/Decorator";
import { Manager } from "../common/Manager";
import MsgMgr from "../event/MsgMgr";
import Global from "../Global";
import StartUp from "../StartUp";
import UINode from "./UINode";

const { ccclass, property } = cc._decorator;

@selfCls
export default class UIMgr extends Manager {
    get parentRoot(): cc.Node {
        return StartUp.instance.uiRoot;
    }

    /////////////////////////////////////////层
    private _topRoot: cc.Node;
    private _bottomRoot: cc.Node;
    private _normalRoot: cc.Node;
    public get topRoot(): cc.Node {
        return this._topRoot;
    }
    public get bottomRoot(): cc.Node {
        return this._bottomRoot;
    }
    public get normalRoot(): cc.Node {
        return this._normalRoot;
    }
    private splitUIRoot() {
        this._topRoot = new cc.Node("Top");
        this._bottomRoot = new cc.Node("Bottom");
        this._normalRoot = new cc.Node("Normal");
        this._topRoot.zIndex = 20;
        this._bottomRoot.zIndex = 0;
        this._normalRoot.zIndex = 1;
        StartUp.instance.uiRoot.addChild(this._topRoot);
        StartUp.instance.uiRoot.addChild(this._bottomRoot);
        StartUp.instance.uiRoot.addChild(this._normalRoot);

        this._topRoot.width = cc.winSize.width;
        this._topRoot.height = cc.winSize.height;
        this._normalRoot.width = cc.winSize.width;
        this._normalRoot.height = cc.winSize.height;
        this._bottomRoot.width = cc.winSize.width;
        this._bottomRoot.height = cc.winSize.height;
    }

    ////////////////////////////////////////////////////////////////////
    private _ready: Map<string, UINode> = new Map<string, UINode>();
    private _all: Map<string, UINode> = new Map<string, UINode>();
    private _focus: UINode = null;

    protected onLoad() {
        this.splitUIRoot();
    }

    public setNormalRootActive(isActive) {
        this._normalRoot.active = isActive;
    }

    public show<T extends UINode>(type: { new(): T; }, args = null) {
        let uiNode = new type();
        let name = uiNode.name;
        if (this._all.has(name)) {
            if (!this._all.get(name).isShow) {
                this._all.get(name).onReshow(args);
            }
        } else {
            if (this._ready.has(name)) { return; }//正在等待ui加载完成
            if (uiNode == null) { return; }
            uiNode.init(args);
            this._ready.set(name, uiNode);
        }
        return uiNode;
    }

    public hide<T extends UINode>(type: { new(): T; }) {
        let uiNode = new type();
        let name = uiNode.name;
        this.hideByName(name);
    }

    public close<T extends UINode>(type: { new(): T; }) {
        let uiNode = new type();
        let name = uiNode.name;
        this.closeByName(name);
    }

    public closeByName(name) {
        if (this._all.has(name)) {
            this._all.get(name).onClose();
            this._all.delete(name);
        }
        if (this._ready.has(name)) {
            this._ready.get(name).onClose();
            this._ready.delete(name);
        }
    }

    public hideByName(name) {
        if (this._all.has(name)) {
            this._all.get(name).onHide();
        }
    }

    public override update(dt) {
        this.inspectReady(dt);//后面可以改成委托通知*
        this.updateUINode(dt);
        this.updateFocusNode(dt);
    }

    private inspectReady(dt) {//检查节点准备好了吗
        let deleteKeyArray = new Array<string>();
        this._ready.forEach((node, name) => {
            if (node.ready) {
                this._all.set(name, node);
                deleteKeyArray.push(name);
                MsgMgr.emit("ON_UI_READY", name);
            }
        })
        for (let i = 0; i < deleteKeyArray.length; i++) {
            let name = deleteKeyArray[i];
            this._ready.delete(name);
        }
    }
    private updateUINode(dt) {
        this._all.forEach((node, name) => {
            if (node.isShow) {
                node.tick(dt);
            } else {
                node.sleepTick(dt);
            }
        })
    }

    private updateFocusNode(dt) {//目前只实现normalRoot的焦点功能 后续需要性能优化
        let focusUI = null;
        let zorder = -1;
        this._all.forEach((node, name) => {
            if (node.zOrder() > zorder && node.isNeedFocus) {
                focusUI = node;
                zorder = node.zOrder();
            }
        })
        if (focusUI == null) { return; }
        if (this._focus == null) {
            this._focus = focusUI;
            this._focus.onFocus();
        } else {
            if (this._focus == focusUI) { return; }
            this._focus.onUnfocus();
            this._focus = focusUI;
            this._focus.onFocus();

        }
    }

    public getByName(name) {
        if (this._all.has(name)) {
            return this._all.get(name);
        } else return null;
    }

    public get focus(): UINode {
        return this._focus;
    }

}
